#include <functional>
#include <future>
#include <utility>
#include <memory>
#include <mutex>
#include <atomic>
#include <condition_variable>
#include "cthread.h"
#include <vector>
#include <chrono>

// enum class  ThreadState{
//     NotRun =0,
//     Running,
//     Finished
// };

class CPoolthread{

public:
    CPoolthread()
    {
        auto now = std::chrono::system_clock::now();

        // 转换为自纪元以来的毫秒数
        auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
            now.time_since_epoch()
        );
        
        idelTime = ms.count();

        m_thread = new CThread(&CPoolthread::Run,this);
        m_thread->start();
    }

    ~CPoolthread()
    {
        if(!IsStoped())
        {
            Stop();
        }
        
        Join();
        if(m_thread)
        {
            delete m_thread;
            m_thread==nullptr;
        }        
    }

    CPoolthread(const CPoolthread& other)=delete;
    //CPoolthread(const CPoolthread&& other)=delete;

public:
    template<typename F,typename... Args>
    void Start(F&& f,Args&&... args)
    {
        std::unique_lock<mutex> lock(m_conditionMtx );
        m_fun(std::bind(std::forward<F>(f),std::forward<Args>(args)...));
        startRun = true;
        //isExeced = false;
        m_runCondition.notify_one();
    }

    template<typename F,typename... Args>
    void AddPending(F&& f,Args&&... args)
    {
         std::unique_lock<mutex> lock(m_conditionMtx );
         m_pendingFuns.emplace_back(std::bind(std::forward<F>(f),std::forward<Args>(args)...));
         //isExeced = false;
         m_runCondition.notify_one();
    }

    int GetPendingsNum()
    {
        std::unique_lock<mutex> lock(m_conditionMtx );
        return m_pendingFuns.size();
    }

    void Run()
    {
        while(true)
        {
            std::function<void()> tmpFun;
            {
                std::unique_lock<mutex> lock(m_conditionMtx) ;
                m_runCondition.wait(lock,[this]{return stop || startRun || !m_pendingFuns.empty();});
                //if(stop || isExeced)
                if(stop)
                {
                    //SendFinishSem();
                    return;
                }

                if(startRun)
                {
                    tmpFun = m_fun;
                    startRun = false;
                }                
            }

            state = ThreadState::Running;          
            if(tmpFun)
            {   
                tmpFun();                
            }

            if(!IsPendingsEmpty())
            {
                DoPendings();
            }
            state = ThreadState::Finished;

            {
                std::unique_lock<mutex> lock(m_conditionMtx) ;

                auto now = std::chrono::system_clock::now();
    
                // 转换为自纪元以来的毫秒数
                auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
                    now.time_since_epoch()
                );
                
                idelTime = ms.count();
                //isExeced = true;
                //m_execedCondition.notify_one();
            }
           
            //SendFinishSem();
        }
    }

    int IdelKeepTime()
    {
        if(state == ThreadState::Running)
        {
            return 0;
        }
        
        std::unique_lock<mutex> lock(m_conditionMtx) ;
        auto now = std::chrono::system_clock::now();
        // 转换为自纪元以来的毫秒数
        auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
            now.time_since_epoch()
        );
        
        return ms.count() - idelTime;
    }

    bool IsStoped()
    {
        return stop.load();
    }

    ThreadState GetState()
    {
        return state.load();
    }

    void Stop()
    {
        std::unique_lock<mutex> lock(m_conditionMtx );
        stop = true;
        m_runCondition.notify_one();        
    }

    void Join()
    {
        if(m_thread)
        {
            m_thread->Join();
        }
        //std::unique_lock<mutex> lock(m_conditionMtx );
        //m_execedCondition.wait(lock,[this]{return isExeced;});
    }

    // static void WaitFinishSem()
    // {
    //     std::unique_lock<mutex> lock(g_finishedConditionMtx) ;
    //     g_finishedCondition.wait(lock,[g_isFinished]{return g_isFinished;});
    //     g_isFinished = false;        
    // }

private:
    void DoPendings()
    {
        for(;;)
        {
            std::function<void()> fun;
            {
               std::unique_lock<mutex> lock(m_conditionMtx);
               if(!m_pendingFuns.empty())
               {
                    fun = m_pendingFuns.front();
                    m_pendingFuns.pop();
               }   
            }

            if(fun)
            {
                fun();
            }
            else
            {
                break;
            }
        }
    }

    bool IsPendingsEmpty()
    {
        td::unique_lock<mutex> lock(m_conditionMtx);
        return m_pendingFuns.empty();
    }


    // void SendFinishSem()
    // {        
    //     std::unique_lock<mutex> lock(g_finishedConditionMtx );
    //     g_isFinished = true;
    //     g_finishedCondition.notify_one();        
    // }
private:
    std::function<void()> m_fun;
    std::atomic<bool> stop{false};
    std::condition_variable m_runCondition;
    //std::condition_variable m_execedCondition;
    std::mutex m_conditionMtx;
    bool startRun{false};
    std::atomic<ThreadState> state{ThreadState::NotRun};
    CThread* m_thread{nullptr};
    //std::mutex m_pendingMtx;
    std::list<std::function<void()>> m_pendingFuns;
    int idelTime;
    //bool isExeced{false};
    //std::atomic<bool> m_havePending{false};

    // static bool g_isFinished{false};
    // static std::mutex g_finishedConditionMtx;
    // static std::condition_variable g_finishedCondition;


}